import { listenFromTopic } from "@nodejs/mq"
import { responseFromBuffer } from "./proto"
import { isErrorMessage, isResponseMessage } from "@core/types"
import { parseJSON } from "@tools/core"
import { Response } from "express"

export function listenResponseQueue(uuid: string, rootProto: protobuf.Root, resMap: Map<string, Response>) {
    return listenFromTopic(`response.topic`, `response.queue.${uuid}`, `response.${uuid}`, async (msg, channel) => {
        try {
            const response = responseFromBuffer(rootProto, msg.content)
            if (isErrorMessage(response)) {
                const payload = response.payload
                if (payload.appid === uuid) {
                    const res = resMap.get(payload.reqid)
                    if (res) {
                        const data = parseJSON(payload.data.toString())
                        res.toFail(payload.message, { ...data, stack: payload.stack })
                    }
                    resMap.delete(payload.reqid)
                    channel.ack(msg)
                    return;
                }
                channel.nack(msg)
                return;
            }
            if (isResponseMessage(response)) {
                const payload = response.payload
                if (payload.appid === uuid) {
                    const res = resMap.get(payload.reqid)
                    if (res) {
                        const data = parseJSON(payload.data.toString())
                        const headers = parseJSON(payload.headers.toString())
                        if (headers) {
                            Object.keys(headers).map(key => {
                                const val = headers[key];
                                res.setHeader(key, val)
                            })
                        }
                        res.toSuccess(data)
                    } else {
                        console.log(`res not found ${payload.reqid}`)
                    }
                    resMap.delete(payload.reqid)
                    channel.ack(msg)
                    return;
                }
                channel.nack(msg)
                return;
            }
            channel.ack(msg)
            return;
        } catch (e) {
            console.error(e)
            console.log(msg.content)
            channel.ack(msg)
        }
    }, {
        durable: true
    })
}